module Main where 
import Metrics
import IO

parseBlameLine :: String -> (String, String)
parseBlameLine s = 
	let w = words s;
		w1 = w!!1; w2 = if (length w >2) then w!!2 else "-"
	in (w1, w2)

parseBlame :: [String] -> [(String, String)]
parseBlame = map parseBlameLine

getRH :: Maybe FilePath -> IO Handle
getRH Nothing = return stdin
getRH (Just fn) = openFile fn ReadMode

getWH :: Maybe FilePath -> IO Handle
getWH Nothing = return stdout
getWH (Just fn) = openFile fn WriteMode

readLines :: Handle -> IO [String]
readLines = readLines' [] 
	where readLines' result h = 
		do { 
			line <- catch (hGetLine h) (\e -> return "");
			if (line == "") then return result else do readLines' (result++[line]) h
		}
			
printArray :: Show a => [a]->IO ()
printArray [] = return ()
printArray (a:as) = do
	print a
	printArray as


apply x f = f $ x

{-
weightsList :: [(String, Weight String)]
weightsList = [("Lines", m), ("Words", wordsWeight), ("Chars",)]
-}

weights :: [(String, Weight [String])]
weights = [
	("Lines", linesWeight),
	("Characters", charsWeight)]

metricsList :: [(String, Metrics String String)]
metricsList = [
	("Blending      ", blending),
	("Fragmentation ", fragmentation),
	("Dispersion    ", dispersion),
	("Disturbance   ", disturbance)
	]

applyMetrics :: Weight [b] -> [Metrics a b] -> [(a,b)] -> [Double]
applyMetrics w mx dat = map (\m -> m w dat) mx

applyAllMetrics :: [Weight [b]] -> [Metrics a b] -> 
	[(a,b)] -> [[Double]]
applyAllMetrics ws ms dat = map (\w->applyMetrics w ms dat) ws

transposeMatrix :: [[a]] -> [[a]]
transposeMatrix [] = []
transposeMatrix [[]] = [[]]
transposeMatrix m = (map head m) : (transposeMatrix (map tail m))

prepareResults :: [a] -> [b] -> [[c]] -> [(a, [(b, c)])]
prepareResults h1 h2 dat = zip h1 (map (zip h2) dat)

printResults :: Show a => [a] -> IO ()
printResults [] = return ()
printResults (a:as) = do
	print a
-- //	let (h,v)=a in putStrLn (h ++ ": " ++ show v)
	printResults as

main = do
	input <- (readLines stdin) 
	inputData <- return $ parseBlame input
	results <- return $ applyAllMetrics (map snd weights) (map snd metricsList) inputData
	printResults $ prepareResults (map fst metricsList) (map fst weights) (transposeMatrix results)
